//===========================================================================
/**
 *
 *	@file		break_poke.c
 *	@brief		ポケモン操作/管理
 *	@author		hosaka genya
 *	@data		2008.11.13
 *
 */
//=============================================================================
#include "common.h"
#include "system/clact_tool.h"
#include "system/snd_tool.h"

#include "../../pkthln_comm_pack.h"
#include "../../poke_clact.h"
#include "../../poke_clact_move.h"
#include "../../pkthln_poke_act.h"
#include "../../pokethlon.h"
#include "../event_se_def.h"
#include "../evt_cats.h"
#include "../pkthln_evt_info.naix"

#include "break_common.h"
#include "break_poke.h"

#include "pkthev_break.naix"
#include "break_obj_main_NANR_LBLDEFS.h"
#include "break_obj_sub_NANR_LBLDEFS.h"

typedef struct COMM_POKE_tag * COMM_POKE_PTR;

//=============================================================================
/**
 *								定数定義
 */
//=============================================================================

enum {
	CAP_ID_M_POKEGRA = 0,
	CAP_ID_M_AURA,
	CAP_ID_M_EFF,
	CAP_ID_M_SMOKE,
	CAP_ID_M_BALL,
	CAP_ID_S_POKEGRA_A,	//1:順番入れ替え不可
	CAP_ID_S_POKEGRA_B,	//2:順番入れ替え不可
	CAP_ID_S_POKEEFF_A,	//3:順番入れ替え不可
	CAP_ID_S_POKEEFF_B, //4:順番入れ替え不可
	CAP_ID_MAX,

	// COMM_POKE のOBJ
	CAPCOMM_ID_M_KAWARA = 0,
	CAPCOMM_ID_M_KAWARA_EFF,
	CAPCOMM_ID_M_EFF,
	CAPCOMM_ID_M_AURA,
	CAPCOMM_ID_M_SMOKE,
	CAPCOMM_ID_M_BALL,
	CAPCOMM_ID_MAX,
};

//=============================================================================
/**
 *								構造体定義
 */
//=============================================================================

//--------------------------------------------------------------
///	自分のポケモン管理ワーク
//==============================================================
typedef struct BREAK_POKE_tag {
	// [in]
	HEAPID HeapID;
	CATS_SYS_PTR csp;
	CATS_RES_PTR crp;
	PKTHLN_PTR work;	///< スロンワーク
	// [private]
	CATS_ACT_PTR cap[ CAP_ID_MAX ];
	BREAK_POKE_PARAM Param[ ENTRY_MAX ];

	u32 PokeIdx : 2;		///< 参照ポケモンのIDX
	u32 State : 8;			///< 状態
	u32 HealTimer : 11;
	u32 TensionTimer : 11;

	u32 Tension : 8;		///< テンション値
	u32 bHighTension : 1;	///< ハイテンションフラグ
	u32 bSweat : 1;
	u32 SubSeq : 6;
	u32 AttackTimer : 8;
	u32	ChangeTimer : 8;
} BREAK_POKE;

//--------------------------------------------------------------
///	通信ポケモン表示用ワーク
//==============================================================
typedef struct COMM_POKE_tag {
	// [in]
	PKTHLN_PTR PkthlnWork;
	POKE_ACT_PTR act[ ENTRY_MAX ];
	u32 StaminaMax[ ENTRY_MAX ];
	// [private]
	CATS_ACT_PTR cap[ CAPCOMM_ID_MAX ];
	TCB_PTR	tcbChange;
	u32 ChangeAfterIdx : 2;	///< 交換後に表示するポケモンのIDX
	u32 ChangeSeq : 4;
	u32 ChangeTimer : 8;
	u32 bChange : 1;
	u32 BreakCountPre : 8;	///< 前回のカワラ枚数
	u32 PokeIdx : 2;		///< 参照ポケモンのIDX
	u32 NetID : 2;			///< ネットIDX
	u32 LineID : 2;			///< 後列のIDX(左詰め)
	u32 DummyBit : 3;
} COMM_POKE;

//--------------------------------------------------------------
///	通信ポケモン表示管理用ワーク
//==============================================================
typedef struct COMM_POKE_CNT_tag {
	// [in]
	HEAPID HeapID;
	CATS_SYS_PTR csp;
	CATS_RES_PTR crp;
	PKTHLN_PTR work;	///< スロンワーク
	POKE_ACT_CNT_PTR PokeActCntPtr;
	// [private]
	COMM_POKE poke[ COMM_POKE_MAX ];
} COMM_POKE_CNT;

//=============================================================================
/**
 *							プロトタイプ宣言
 */
//=============================================================================
// -- prototype --
static void _BreakPoke_ProcNormal( BREAK_POKE_PTR ptr, BOOL bKawaraMaking );
static void _BreakPoke_ProcAttack( BREAK_POKE_PTR ptr );
static void _BreakPoke_ProcPanic( BREAK_POKE_PTR ptr );
static void _BreakPoke_ProcChange( BREAK_POKE_PTR ptr );
static void _BreakPoke_StaminaProc( BREAK_POKE_PTR ptr );
static void CommPoke_Setup( COMM_POKE_PTR ptr, CATS_SYS_PTR csp, CATS_RES_PTR crp, POKE_ACT_CNT_PTR cntAct, u8 NetID, PKTHLN_PTR work, u32* StaminaMax );
static void CommPoke_Proc( COMM_POKE_PTR ptr );
static void OBJ_AddPokegra( CATS_ACT_PTR* ppCap, CATS_SYS_PTR csp, CATS_RES_PTR crp );
static void OBJ_TransPokeGra( BREAK_POKE_PTR ptr, u16 CapIdx, u8 TeamIdx, u8 PokeIdx, BOOL b_LCD_main );
static void SetState( BREAK_POKE_PTR ptr, BPOKE_STATE state );
static void TensionProc( BREAK_POKE_PTR ptr );
static void TensionAdd( BREAK_POKE_PTR ptr, BOOL bCritical, u16 breakNum );
static BOOL SweatCalcSpeed( CATS_ACT_PTR cap, fx32 stamina, fx32 staminaMax );
static void HighTension_Start( BREAK_POKE_PTR ptr );
static void HighTension_End( BREAK_POKE_PTR ptr );
static void PKACT_Init( POKE_ACT_CNT_PTR PokeActCntPtr, const u8 CurrentID );
static void DrawTensionAuraS( CATS_ACT_PTR cap, u16 Tension, BOOL bSE );
static void SetBenchPokePos( BREAK_POKE_PTR ptr, u32 PokeIdx, s16 px, s16 py );

//--------------------------------------------------------------
///	デバッグフラグ
//==============================================================
#define DEBUG_PRINT_TOUCH_SPAN ///< タッチ間隔をプリント

#ifdef DEBUG_PRINT_TOUCH_SPAN
static int g_debug_timer = 0;
#endif

//============================================================
//
// ■ とりあえず関数置き場 __TempFunc__
//
//============================================================



//=============================================================================
/**
 *								外部公開関数
 */
//=============================================================================

//-----------------------------------------------------------------------------
/**
 *	@brief	かわらわりポケモンコントローラー 生成
 *
 *	@param	HEAPID HeapID
 *	@param	csp
 *	@param	crp
 *	@param	CurrentID
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
BREAK_POKE_PTR BreakPoke_Create( HEAPID HeapID, CATS_SYS_PTR csp, CATS_RES_PTR crp, PKTHLN_PTR work )
{
	BREAK_POKE_PTR ptr;
	u8 CurrentID;

	CurrentID = PTFrameGetCurrentID(work);

	ptr = sys_AllocMemory( HeapID, sizeof(BREAK_POKE) );
	MI_CpuClear8( ptr, sizeof(BREAK_POKE) );

	ptr->HeapID = HeapID;
	ptr->csp = csp;
	ptr->crp = crp;
	ptr->work = work;
	ptr->Tension = 0;

	SetBreakPokeParam( ptr->Param, CurrentID, work );

	// ポケグラをロード
	OBJ_AddPokegra( ptr->cap, ptr->csp, ptr->crp );

	// 状態異常アイコン
	{
		s16 px, py;

		CATS_ObjectPosGetCap_SubSurface( ptr->cap[ CAP_ID_S_POKEGRA_A ], &px, &py, OBJ_DISTANCE );
		py += BENCH_POKEEFF_POS_Y_DIFF;
		ptr->cap[ CAP_ID_S_POKEEFF_A ] = OBJ_AddCommonSub( csp, crp, px, py, NANR_break_obj_sub_sweat, PRISUB_POKE_EFF );
		CATS_ObjectEnableCap( ptr->cap[ CAP_ID_S_POKEEFF_A ], CATS_ENABLE_FALSE );

		CATS_ObjectPosGetCap_SubSurface( ptr->cap[ CAP_ID_S_POKEGRA_B ], &px, &py, OBJ_DISTANCE );
		py += BENCH_POKEEFF_POS_Y_DIFF;
		ptr->cap[ CAP_ID_S_POKEEFF_B ] = OBJ_AddCommonSub( csp, crp, px, py, NANR_break_obj_sub_sweat, PRISUB_POKE_EFF );
		CATS_ObjectEnableCap( ptr->cap[ CAP_ID_S_POKEEFF_B ], CATS_ENABLE_FALSE );
	}

	{
		s16 px, py;

		// テンションアクターを生成
		CATS_ObjectPosGetCap( ptr->cap[ CAP_ID_M_POKEGRA ], &px, &py );
		ptr->cap[ CAP_ID_M_AURA ] = OBJ_AddCommon( csp, crp, px, py, NANR_break_obj_main_Aura_S, PRI_AURA );
		CATS_ObjectEnableCap( ptr->cap[ CAP_ID_M_AURA ], CATS_ENABLE_FALSE );

		// 煙を生成
		ptr->cap[ CAP_ID_M_SMOKE ] = OBJ_AddCommon( csp, crp, px, py, NANR_break_obj_main_Smoke_L, PRI_SMOKE );
		CATS_ObjectEnableCap( ptr->cap[ CAP_ID_M_SMOKE ], CATS_ENABLE_FALSE );

		// ボールを生成
		ptr->cap[ CAP_ID_M_BALL ] = OBJ_AddCommon( csp, crp, px, py, NANR_break_obj_main_EffChangeBall, PRI_BALL );
		CATS_ObjectEnableCap( ptr->cap[ CAP_ID_M_BALL ], CATS_ENABLE_FALSE );

		// エフェクトアイコンアクターを生成
		px += BREAK_POKE_ICON_DIFF_X;
		py += BREAK_POKE_ICON_DIFF_Y;
		ptr->cap[ CAP_ID_M_EFF ] = OBJ_AddCommon( csp, crp, px, py, NANR_break_obj_main_EffSweat, PRI_POKE_EFFECT );
		CATS_ObjectEnableCap( ptr->cap[ CAP_ID_M_EFF ], CATS_ENABLE_FALSE );
	}

	// ポケグラを転送
	OBJ_TransPokeGra( ptr, CAP_ID_M_POKEGRA, CurrentID, 0, TRUE );
	OBJ_TransPokeGra( ptr, CAP_ID_S_POKEGRA_A, CurrentID, 2, FALSE );
	OBJ_TransPokeGra( ptr, CAP_ID_S_POKEGRA_B, CurrentID, 1, FALSE );

	return ptr;
}

//-----------------------------------------------------------------------------
/**
 *	@brief	かわらわりポケモンコントローラー 削除
 *
 *	@param	BREAK_POKE_PTR ptr
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
void BreakPoke_Delete( BREAK_POKE_PTR ptr )
{
	int i;

	GF_ASSERT(ptr);

	for(i=0; i<CAP_ID_MAX; i++)
	{
		if( ptr->cap[i] ){ CATS_ActorPointerDelete_S(ptr->cap[i]); }
	}

	sys_FreeMemoryEz(ptr);
}

//-----------------------------------------------------------------------------
/**
 *	@brief	かわらわりポケモンコントローラー 主処理
 *
 *	@param	BREAK_POKE_PTR ptr
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
void BreakPoke_Proc( BREAK_POKE_PTR ptr, BOOL bKawaraMaking )
{
	GF_ASSERT(ptr);

	switch( ptr->State )
	{
		case BPOKE_STATE_NORMAL :
			_BreakPoke_ProcNormal( ptr, bKawaraMaking );
			break;
		case BPOKE_STATE_ATTACK :
			_BreakPoke_ProcAttack( ptr );
			break;
		case BPOKE_STATE_PANIC :
			_BreakPoke_ProcPanic( ptr );
			break;
		case BPOKE_STATE_CHANGE :
			_BreakPoke_ProcChange( ptr );
			break;

		default : GF_ASSERT(0);
	}

#ifdef DEBUG_PRINT_TOUCH_SPAN
	g_debug_timer++;
#endif

	// かわら補給状態以外
	if( bKawaraMaking == FALSE )
	{
		// テンション下げる
		TensionProc( ptr );
	}

	// スタミナ処理(回復など)
	// ※現状、交代した瞬間に次のポケモンの処理に入ってしまう仕様
	_BreakPoke_StaminaProc( ptr );
	StaminaProc( ptr->Param, ptr->HealTimer, ptr->PokeIdx );
	ptr->HealTimer++;

	// ニトロキャラクターで設定した移動量の取得
	if( CATS_ObjectAnimeActiveCheckCap( ptr->cap[ CAP_ID_M_POKEGRA ] ) )
	{
		NNSG2dAnimController* pAnimCtrl;
		NNSG2dAnimDataT* anmRes;
		s16 px, py;

		// アニメーション結果を取得
		pAnimCtrl = CLACT_GetAnimController( ptr->cap[ CAP_ID_M_POKEGRA ]->act );
		anmRes = NNS_G2dGetAnimCtrlCurrentElement(pAnimCtrl);

		GF_ASSERT( NNS_G2dIsAnimCtrlActive(pAnimCtrl) );

		// 基底OBJの座標を取得
		CATS_ObjectPosGetCap( ptr->cap[ CAP_ID_M_POKEGRA ], &px, &py );
		px += anmRes->px;
		py += anmRes->py;

		// オーラ追随
		CATS_ObjectPosSetCap( ptr->cap[ CAP_ID_M_AURA ], px, py );

		// エフェクトアイコン追随
		px += BREAK_POKE_ICON_DIFF_X;
		py += BREAK_POKE_ICON_DIFF_Y;
		CATS_ObjectPosSetCap( ptr->cap[ CAP_ID_M_EFF ], px, py );
	}
}

//-----------------------------------------------------------------------------
/**
 *	@brief	攻撃処理
 *
 *	@param	BREAK_POKE_PTR ptr
 *	@param	bCritical
 *	@param	breakNum
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
void BreakPoke_Attack( BREAK_POKE_PTR ptr, BOOL bCritical, u16 breakNum )
{

#ifdef DEBUG_PRINT_TOUCH_SPAN
	HOSAKA_PRINT("攻撃にかかったフレーム: %d \n", g_debug_timer );
	g_debug_timer = 0;
#endif

	GF_ASSERT( ptr->State != BPOKE_STATE_PANIC );

	// キャンセル時のスタミナ演算
	if( ptr->State == BPOKE_STATE_ATTACK )
	{
		BREAK_POKE_PARAM* bpp = &ptr->Param[ ptr->PokeIdx ];

		// スタミナ減算
		bpp->Stamina = StaminaCalc( bpp->Stamina, ptr->AttackTimer );
		// 気絶判定
		if( bpp->Stamina <= 0 )
		{
			SetState( ptr, BPOKE_STATE_PANIC );
			return; // 攻撃動作フラグも立てない
		}
	}

	// テンションアップ処理
	if( ptr->bHighTension == FALSE )
	{
		TensionAdd( ptr, bCritical, breakNum );
	}

	// 攻撃アニメ
	CATS_ObjectAnimeSeqSetCap( ptr->cap[ CAP_ID_M_POKEGRA ], POKEGRA_SEQ_ATTACK );

	// AP:体当たり
	PTFrame_AddActionPoint( ptr->work, PTFrameGetCurrentID(ptr->work), ptr->PokeIdx, ADD_TYPE_ATTACK, 1 );

	// ATTACK状態へ(初期化)
	SetState( ptr, BPOKE_STATE_ATTACK );
}

//-----------------------------------------------------------------------------
/**
 *	@brief	交代開始処理
 *
 *	@param	BREAK_POKE_PTR ptr
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
void BreakPoke_Change( BREAK_POKE_PTR ptr )
{
	GF_ASSERT( ptr->State != BPOKE_STATE_CHANGE );

	// 交代開始
	SetState( ptr, BPOKE_STATE_CHANGE );
}

//-----------------------------------------------------------------------------
/**
 *	@brief	終了処理
 *
 *	@param	BREAK_POKE_PTR ptr
 *	@param	b_auto_anime
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
void BreakPoke_SetAutoAnime( BREAK_POKE_PTR ptr, BOOL b_auto_anime )
{
	int i;

	GF_ASSERT(ptr);

	for(i=0; i<CAP_ID_MAX; i++)
	{
		if( ptr->cap[i] ){ CATS_ObjectAutoAnimeSetCap(ptr->cap[i], b_auto_anime); }
	}
}

//-----------------------------------------------------------------------------
/**
 *	@brief	状態取得
 *
 *	@param	BREAK_POKE_PTR ptr
 *	@param	seq
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
BPOKE_STATE BreakPoke_GetState( BREAK_POKE_PTR ptr )
{
	GF_ASSERT(ptr);
	return ptr->State;
}

//-----------------------------------------------------------------------------
/**
 *	@brief	交代可能状態か判定
 *
 *	@param	BREAK_POKE_PTR ptr
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
BOOL BreakPoke_CheckChangeEnable( BREAK_POKE_PTR ptr )
{
	return( ptr->State == BPOKE_STATE_NORMAL || ptr->State == BPOKE_STATE_ATTACK );
}

//-----------------------------------------------------------------------------
/**
 *	@brief	パラメータ取得
 *
 *	@param	BREAK_POKE_PTR ptr
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
const BREAK_POKE_PARAM* BreakPoke_GetActiveParam( BREAK_POKE_PTR ptr )
{
	GF_ASSERT(ptr);
	return ( &ptr->Param[ ptr->PokeIdx ] );
}

//-----------------------------------------------------------------------------
/**
 *	@brief	ハイテンションフラグを取得
 *
 *	@param	BREAK_POKE_PTR ptr
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
BOOL BreakPoke_GetHighTensionFlag( BREAK_POKE_PTR ptr )
{
	GF_ASSERT(ptr);
	return ( ptr->bHighTension );
}

//-----------------------------------------------------------------------------
/**
 *	@brief	汗状態フラグを取得
 *
 *	@param	BREAK_POKE_PTR ptr
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
BOOL BreakPoke_GetSweatFlag( BREAK_POKE_PTR ptr )
{
	GF_ASSERT(ptr);

	return( ptr->bSweat );
}

//-----------------------------------------------------------------------------
/**
 *	@brief	テンション値を取得
 *
 *	@param	BREAK_POKE_PTR ptr
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
u16 BreakPoke_GetTension( BREAK_POKE_PTR ptr )
{
	GF_ASSERT(ptr);
	return ( ptr->Tension );
}

//-----------------------------------------------------------------------------
/**
 *	@brief
 *
 *	@param	BREAK_POKE_PTR ptr
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
u8 BreakPoke_GetPokeIdx( BREAK_POKE_PTR ptr )
{
	GF_ASSERT(ptr);
	return ( ptr->PokeIdx );
}

//-----------------------------------------------------------------------------
/**
 *	@brief	攻撃可能な状態かどうかを取得
 *
 *	@param	BREAK_POKE_PTR ptr
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
BOOL BreakPoke_IsAttackEnable( BREAK_POKE_PTR ptr )
{
	GF_ASSERT(ptr);

	return	( ( ptr->State == BPOKE_STATE_NORMAL ) ||
			  ( ptr->State == BPOKE_STATE_ATTACK && ptr->AttackTimer >= ATTACK_DERAY_SYNC )
			);
}

//-----------------------------------------------------------------------------
/**
 *	@brief	通信ポケモンコントローラー 生成
 *
 *	@param	HEAPID HeapID
 *	@param	csp
 *	@param	crp
 *	@param	work
 *	@param	PokeActCntPtr
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
COMM_POKE_CNT_PTR CommPokeCnt_Create( HEAPID HeapID, CATS_SYS_PTR csp, CATS_RES_PTR crp, PKTHLN_PTR work, POKE_ACT_CNT_PTR PokeActCntPtr )
{
	int i;
	int Count = 0;
	COMM_POKE_CNT_PTR cnt;
	BREAK_POKE_CONV_DATA conv_data;
	u8 CurrentID;

	CurrentID = PTFrameGetCurrentID(work);

	// コンバートデータをロード
	ArchiveDataLoad( &conv_data, ARC_PKTHEVT_PARAM, NARC_pkthln_evt_info_break_bin );

	// ヒープからワークメモリ確保
	cnt = sys_AllocMemory( HeapID, sizeof(COMM_POKE_CNT) );
	MI_CpuClear8( cnt, sizeof(COMM_POKE_CNT) );

	cnt->HeapID = HeapID;
	cnt->csp = csp;
	cnt->crp = crp;
	cnt->work = work;
	cnt->PokeActCntPtr = PokeActCntPtr;

	// ポケセルアクター 座標などもろもろ設定
	PKACT_Init( PokeActCntPtr, CurrentID );

	// 通信相手のポケモンを表示
	for( i=0; i<ENTRY_MEMBER_NUM_MAX; i++ )
	{
		if( i != CurrentID )
		{
			int pk_cnt;
			u32 StaminaMax[ENTRY_MAX];

			// スタミナ最大値を保持
			for( pk_cnt=0; pk_cnt<ENTRY_MAX; pk_cnt++ )
			{
				const POKE_SPEC* poke_spec = PTFrame_GetPokeSpec( work, i, pk_cnt );
				StaminaMax[pk_cnt] = conv_data.stamina[ poke_spec->Stamina ];
			}

			CommPoke_Setup( &cnt->poke[Count], csp, crp, cnt->PokeActCntPtr ,i, work, StaminaMax );
			Count++;
		}
	}

	return cnt;
}

//-----------------------------------------------------------------------------
/**
 *	@brief	通信ポケモンコントローラー 削除
 *
 * 	@param	COMM_POKE_CNT_PTR cnt
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
void CommPokeCnt_Delete( COMM_POKE_CNT_PTR cnt )
{
	int i,j;

	GF_ASSERT(cnt);

	for( i=0; i<COMM_POKE_MAX; i++ )
	{
		// CAP削除
		for( j=0; j<CAPCOMM_ID_MAX; j++ )
		{
			if(	cnt->poke[i].cap[j] )
			{
				CATS_ActorPointerDelete_S( cnt->poke[i].cap[j] );
			}
		}
	}



	sys_FreeMemoryEz( cnt );
}

//-----------------------------------------------------------------------------
/**
 *	@brief	通信ポケモンコントローラー 主処理
 *
 *	@param	COMM_POKE_CNT_PTR cnt
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
void CommPokeCnt_Proc( COMM_POKE_CNT_PTR cnt )
{
	int i;

	for( i=0; i<COMM_POKE_MAX; i++ )
	{
		CommPoke_Proc( &cnt->poke[i] );
	}
}

//-----------------------------------------------------------------------------
/**
 *	@brief
 *
 *	@param	COMM_POKE_CNT_PTR cnt
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
void CommPokeCnt_Finish( COMM_POKE_CNT_PTR cnt )
{
	int i,j;

	// 全員止める
	for( i=0; i<COMM_POKE_MAX; i++ )
	{
		COMM_POKE* pPoke = &cnt->poke[i];
		PokeAct_SetAnm( pPoke->act[ pPoke->PokeIdx ], ANM_TYPE_STOP );

		// TCB強制終了
		if( pPoke->tcbChange != NULL )
		{
			TCB_Delete( pPoke->tcbChange );
			pPoke->tcbChange = NULL;
		}

		// エフェクトも止める
		for( j=0; j<CAPCOMM_ID_MAX; j++ )
		{
			CATS_ObjectAutoAnimeSetCap( pPoke->cap[j], FALSE );
		}
	}
}

//=============================================================================
/**
 *								static関数
 */
//=============================================================================

static void _BreakPoke_ProcNormal( BREAK_POKE_PTR ptr, BOOL bKawaraMaking )
{
	if( bKawaraMaking == FALSE &&
		CATS_ObjectAnimeActiveCheckCap( ptr->cap[ CAP_ID_M_POKEGRA ] ) == FALSE )
	{
		// アニメのSTOPを検知して、ポケモンアニメ復帰
		CATS_ObjectAnimeSeqSetCap( ptr->cap[ CAP_ID_M_POKEGRA ], POKEGRA_SEQ_STEP );
	}
//	HOSAKA_PRINT("tension:%d \n", ptr->Tension);
}

//-----------------------------------------------------------------------------
/**
 *	@brief	攻撃シーケンス
 *
 *	@param	BREAK_POKE_PTR ptr
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static void _BreakPoke_ProcAttack( BREAK_POKE_PTR ptr )
{
	if( ++ptr->AttackTimer >= ATTACK_SYNC )
	{
		SetState( ptr, BPOKE_STATE_NORMAL );
	}
}

//-----------------------------------------------------------------------------
/**
 *	@brief	気絶シーケンス
 *
 *	@param	BREAK_POKE_PTR ptr
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static void _BreakPoke_ProcPanic( BREAK_POKE_PTR ptr )
{
	if( ptr->Param[ ptr->PokeIdx ].Stamina >= PANIC_REFLESH_POINT )
	{
		SetState( ptr, BPOKE_STATE_NORMAL );
		HOSAKA_PRINT("Panic recover!! \n" );
	}
}

//-----------------------------------------------------------------------------
/**
 *	@brief	交代シーケンス
 *
 *	@param	BREAK_POKE_PTR ptr
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static void _BreakPoke_ProcChange( BREAK_POKE_PTR ptr )
{
	// @@@ 交換にかかったフレーム数表示
#ifdef PM_DEBUG
	static int debug_hoge = 0;
	debug_hoge++;
#endif

	switch( ptr->SubSeq )
	{
	case 0:
		{
			// 煙表示
			CATS_ObjectAnimeReStartCap( ptr->cap[ CAP_ID_M_SMOKE ] );
			CATS_ObjectEnableCap( ptr->cap[ CAP_ID_M_SMOKE ], CATS_ENABLE_TRUE );
			// 打ち上げSE
			Snd_SePlay( SE_BREAK_CHANGE_OUT1 );
		}
		ptr->SubSeq++;
		break;
	case 1:
		if( ++ptr->ChangeTimer >= CHANGE_POKEGRA_SYNC)
		{
			// モンスターボール表示
			CATS_ObjectAnimeReStartCap( ptr->cap[ CAP_ID_M_BALL ] );
			CATS_ObjectAutoAnimeSetCap( ptr->cap[ CAP_ID_M_BALL ], FALSE );
			CATS_ObjectEnableCap( ptr->cap[ CAP_ID_M_BALL ], CATS_ENABLE_TRUE );
			// メインポケグラを消す
			CATS_ObjectEnableCap( ptr->cap[ CAP_ID_M_POKEGRA ], CATS_ENABLE_FALSE );
			CATS_ObjectEnableCap( ptr->cap[ CAP_ID_M_AURA ], CATS_ENABLE_FALSE );
			CATS_ObjectEnableCap( ptr->cap[ CAP_ID_M_EFF ], CATS_ENABLE_FALSE );

			ptr->ChangeTimer = 0;
			ptr->SubSeq++;
		}
		break;
	case 2:
		// ボール移動(回収)、ベンチポケグラ スロットアウト
		{
			s16 px, py;
			s16 my;

			CATS_ObjectPosGetCap( ptr->cap[ CAP_ID_M_BALL ], &px, &py );
			my = ( BALL_OUT_TARGET_POS - py ) / BALL_OUT_SPEED_DIV;

			if( py <= BALL_OUT_TARGET_POS + BALL_OUT_TARGET_POS_DIFF || my == 0 )
			{
				s8 LoadPokeIdx;

				LoadPokeIdx = ptr->PokeIdx - 1;
				if( LoadPokeIdx < 0 ){ LoadPokeIdx = ENTRY_MAX-1; }

				// 次SEQでスロットインするポケモンをロード
				OBJ_TransPokeGra( ptr, CAP_ID_S_POKEGRA_B, PTFrameGetCurrentID(ptr->work), LoadPokeIdx, FALSE );

				// ベンチポケグラの位置をセット
				px = BENCH_POKE_POS_X;
				py = BENCH_POKE_POS_Y - BENCH_POKE_POS_Y_OFS;
				SetBenchPokePos( ptr, CAP_ID_S_POKEGRA_B, px, py );

				ptr->SubSeq++;
			}
			else
			{
				CATS_ObjectPosSetCap_SubSurface( ptr->cap[ CAP_ID_M_BALL ], px, py + my ,OBJ_DISTANCE );

				// 同時にベンチポケグラも捌ける
				{
					const s16 TarPos = GX_LCD_SIZE_Y + 80;

					CATS_ObjectPosGetCap_SubSurface( ptr->cap[ CAP_ID_S_POKEGRA_B ], &px, &py, OBJ_DISTANCE );
					py += MATH_ABS(TarPos - py) >> 2;
					py = MATH_IMin( py, 216 );

					SetBenchPokePos( ptr, CAP_ID_S_POKEGRA_B, px, py );
				}
			}
		}
		break;
	case 3:
		// ベンチポケグラ スロットイン
		{
			const s16 TarPos = BENCH_POKE_POS_Y + BENCH_POKE_POS_Y_OFS;
			s16 px, py, my;

			CATS_ObjectPosGetCap_SubSurface( ptr->cap[ CAP_ID_S_POKEGRA_A ], &px, &py, OBJ_DISTANCE );
			my = MATH_ABS(TarPos - py) >> 1;

			if( TarPos > py )
			{
				if( my == 0 ){ my = 1; } // 誤差調整
				// ポケモンA
				py += my;
				SetBenchPokePos( ptr, CAP_ID_S_POKEGRA_A, px, py );
				// ポケモンB
				CATS_ObjectPosGetCap_SubSurface( ptr->cap[ CAP_ID_S_POKEGRA_B ], &px, &py, OBJ_DISTANCE );
				py += my;
				SetBenchPokePos( ptr, CAP_ID_S_POKEGRA_B, px, py );
			}
		}

		// 次のポケモンボールを投げる
		if( ++ptr->ChangeTimer >= CHANGE_WAIT_SYNC )
		{
			// ベンチポケグラ移動終了
			{
				// ベンチポケグラアクターの参照先交換
				CATS_ACT_PTR capTemp;
				// ポケ
				capTemp = ptr->cap[ CAP_ID_S_POKEGRA_A ];
				ptr->cap[ CAP_ID_S_POKEGRA_A ] = ptr->cap[ CAP_ID_S_POKEGRA_B ];
				ptr->cap[ CAP_ID_S_POKEGRA_B ] = capTemp;
				// 状態異常アイコン
				capTemp = ptr->cap[ CAP_ID_S_POKEEFF_A ];
				ptr->cap[ CAP_ID_S_POKEEFF_A ] = ptr->cap[ CAP_ID_S_POKEEFF_B ];
				ptr->cap[ CAP_ID_S_POKEEFF_B ] = capTemp;
				// 座標を強制置換
				SetBenchPokePos( ptr, CAP_ID_S_POKEGRA_A, BENCH_POKE_POS_X, BENCH_POKE_POS_Y );
				SetBenchPokePos( ptr, CAP_ID_S_POKEGRA_B, BENCH_POKE_POS_X, BENCH_POKE_POS_Y + BENCH_POKE_POS_Y_OFS );
			}

			// ボール位置初期化
			{
				s16 py;
				py = BALL_IN_DEF_POS;
				CATS_ObjectPosSetCap_SubSurface( ptr->cap[ CAP_ID_M_BALL ], START_POKE_MINE_POS_X, py ,OBJ_DISTANCE );
			}

			Snd_SePlay( SE_BREAK_CHANGE_IN1 );

			ptr->ChangeTimer = 0;
			ptr->SubSeq++;
		}
		break;
	case 4:
		// ボール移動（落下）
		{
			s16 px, py;
			s16 val;

			CATS_ObjectPosGetCap( ptr->cap[ CAP_ID_M_BALL ], &px, &py );

			val = MATH_ABS( BALL_IN_DEF_POS - BALL_IN_DEF_SPD - py );
			if( val ){ val /= BALL_IN_SPEED_DIV; }	///< ZeroDiv 対策
			py += val + BALL_IN_DEC_POS;

			if( py >= START_POKE_MINE_POS_Y )
			{
				Snd_SePlay( SE_BREAK_CHANGE_IN2 );

				// ボールアニメ開始
				CATS_ObjectPosSetCap( ptr->cap[ CAP_ID_M_BALL ], START_POKE_MINE_POS_X, START_POKE_MINE_POS_Y );
				CATS_ObjectAutoAnimeSetCap( ptr->cap[ CAP_ID_M_BALL ], TRUE );
				// 煙表示
				CATS_ObjectAnimeReStartCap( ptr->cap[ CAP_ID_M_SMOKE ] );

				ptr->SubSeq++;
			}
			else
			{
				CATS_ObjectPosSetCap_SubSurface( ptr->cap[ CAP_ID_M_BALL ], px, py ,OBJ_DISTANCE );
			}
		}
		break;
	case 5:
		// 煙ウェイト
		if( ++ptr->ChangeTimer >= CHANGE_POKEGRA_SYNC )
		{
			// ボール消す
			CATS_ObjectEnableCap( ptr->cap[ CAP_ID_M_BALL ], CATS_ENABLE_FALSE );

			// ポケグラ変更
			OBJ_TransPokeGra( ptr, CAP_ID_M_POKEGRA, PTFrameGetCurrentID(ptr->work), ptr->PokeIdx, TRUE );
			ptr->ChangeTimer = 0;

			ptr->SubSeq++;
		}
		break;
	case 6:
#ifdef PM_DEBUG
		{
			HOSAKA_PRINT("交代にかかったフレーム数:%d \n", debug_hoge );
			debug_hoge = 0;
		}
#endif
		// 交代終了
		SetState( ptr, BPOKE_STATE_NORMAL );
		break;
	default : GF_ASSERT(0);
	}
}
//-----------------------------------------------------------------------------
/**
 *	@brief	スタミナに応じて状態異常アイコンを更新
 *
 *	@param	BREAK_POKE_PTR ptr
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static void _BreakPoke_StaminaProc( BREAK_POKE_PTR ptr )
{
	int i;

	// 交換中は更新しない
	if( ptr->State == BPOKE_STATE_CHANGE ){ return; }

	for ( i=0; i<ENTRY_MAX; i++ )
	{
		CATS_ACT_PTR cap;
		u32 anmPanic;
		u32 anmSweat;

		// アクティブポケ
		if( i == ptr->PokeIdx )
		{
			cap = ptr->cap[ CAP_ID_M_EFF ];
			anmPanic = NANR_break_obj_main_EffConfusion;
			anmSweat = NANR_break_obj_main_EffSweat;
			ptr->bSweat = FALSE;
		}
		// 控え
		// ※控えは気絶にならない
		else
		{
			BOOL bDown;
			int benchIdx;	///< ベンチポケモンのIDX(下)

			benchIdx = ptr->PokeIdx + 1;
			if( benchIdx >= ENTRY_MAX ){ benchIdx = 0; }
			bDown = (benchIdx == i);

			cap = ptr->cap[ CAP_ID_S_POKEEFF_A + bDown ];
			anmSweat = NANR_break_obj_sub_sweat;
		}

		// 気絶(ぴより)
		if( ptr->Param[ i ].Stamina <= 0 )
		{
			CATS_ObjectAnimeSeqCheckSetCap( cap, anmPanic );

			if( CATS_ObjectEnableGetCap( cap ) == CATS_ENABLE_FALSE )
			{
				CATS_ObjectEnableCap( cap, CATS_ENABLE_TRUE );
			}

			if( Snd_SePlayCheck(SE_THLON_RUNNING_OUT) == FALSE ){	//再生終了していたら
				Snd_SePlay( SE_THLON_RUNNING_OUT );		//疲労音
			}
		}
		// 汗
		else
		{
			fx32 Stamina = ptr->Param[i].Stamina * FX32_ONE;
			fx32 StaminaMax = ptr->Param[i].StaminaMax * FX32_ONE;

			if( SweatCalcSpeed( cap, Stamina, StaminaMax ) )
			{
				// アニメ表示
				CATS_ObjectAnimeSeqCheckSetCap( cap, anmSweat );
				CATS_ObjectEnableCap( cap, CATS_ENABLE_TRUE );
				// アクティブポケの場合、フラグON
				if( i == ptr->PokeIdx ){ ptr->bSweat = TRUE; }
			}
			else
			{
				// 消す
				CATS_ObjectEnableCap( cap, CATS_ENABLE_FALSE );
				CATS_ObjectAutoAnimeSpeedSetCap( cap, FX32_ONE );
			}
		}
	}
}

//-----------------------------------------------------------------------------
/**
 *	@brief	通信ポケモン 生成
 *
 *	@param	COMM_POKE_PTR ptr
 *	@param	csp
 *	@param	crp
 *	@param	cntAct
 *	@param	NetID
 *	@param	work
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static void CommPoke_Setup( COMM_POKE_PTR ptr, CATS_SYS_PTR csp, CATS_RES_PTR crp, POKE_ACT_CNT_PTR cntAct, u8 NetID, PKTHLN_PTR work, u32* StaminaMax )
{
	int i;

	MI_CpuClear8( ptr, sizeof(COMM_POKE) );
	ptr->NetID = NetID;
	ptr->PkthlnWork = work;

	// 後列のIDXを計算
	ptr->LineID = NetID;
	if( ptr->NetID > PTFrameGetCurrentID(work) )
	{
		ptr->LineID--;
	}

	// ポケモンのデータを取得しておく
	for( i=0; i<ENTRY_MAX; i++ )
	{
		ptr->act[i] = PokeAct_GetPokeActPtr( cntAct, ptr->LineID * ENTRY_MAX + i );
		ptr->StaminaMax[i] = StaminaMax[i];

		HOSAKA_PRINT("[%d]comm StaminaMax[%d]:%d\n",NetID,i,StaminaMax[i]);
	}

	// 通信用バッファを初期化
	{
		COMM_EVENT_COMMON_DATA* data;
		BREAK_CHILD_DATA* child;

		data = PTFrame_GetEvtComCmnData(work);
		child = PKTHLN_CommPack_GetData(&data->ReciveData[NetID]);

		child->Stamina = StaminaMax[0];
	}

	{
		int px, py;

		px = SUB_KAWARA_POS_X + START_POKE_ENEMY_POS_X_OFS * ptr->LineID;
		py = SUB_KAWARA_POS_Y;

		// かわら描画
		ptr->cap[ CAPCOMM_ID_M_KAWARA ] =
			OBJ_AddCommon(	csp, crp, px, py, NANR_break_obj_main_S_Block5, PRI_COMM_KAWARA );

		// かわら破壊エフェクト 生成
		ptr->cap[ CAPCOMM_ID_M_KAWARA_EFF ] =
			OBJ_AddCommon(	csp, crp, px, py, NANR_break_obj_main_EffBreak_S, PRI_COMM_KAWARA_EFF );
		CATS_ObjectEnableCap( ptr->cap[ CAPCOMM_ID_M_KAWARA_EFF ], CATS_ENABLE_FALSE );

		// 基準Y座標をポケモンにあわせる
		py = SUB_ICON_EFFECT_POS_Y;

		// テンションアイコン
		ptr->cap[ CAPCOMM_ID_M_AURA ] =
			OBJ_AddCommon(	csp, crp, px, py, NANR_break_obj_main_Aura_L, PRI_COMM_ICON );
		CATS_ObjectAffineSetCap( ptr->cap[ CAPCOMM_ID_M_AURA ], CLACT_AFFINE_NORMAL );
		CATS_ObjectScaleSetCap( ptr->cap[ CAPCOMM_ID_M_AURA ], 0.7, 0.7 ); //< 縮小
		CATS_ObjectEnableCap( ptr->cap[ CAPCOMM_ID_M_AURA ], CATS_ENABLE_FALSE );

		// 状態異常アイコン
		ptr->cap[ CAPCOMM_ID_M_EFF ] = OBJ_AddCommon( csp, crp, px, py, NANR_break_obj_main_EffSweat, PRI_COMM_ICON );
		CATS_ObjectEnableCap( ptr->cap[ CAPCOMM_ID_M_EFF ], CATS_ENABLE_FALSE );

		// 煙を生成
		ptr->cap[ CAPCOMM_ID_M_SMOKE ] = OBJ_AddCommon( csp, crp, px, py, NANR_break_obj_main_Smoke_S, PRI_COMM_CHANGE );
		CATS_ObjectEnableCap( ptr->cap[ CAPCOMM_ID_M_SMOKE ], CATS_ENABLE_FALSE );

		// ボールを生成
		ptr->cap[ CAPCOMM_ID_M_BALL ] = OBJ_AddCommon( csp, crp, px, py, NANR_break_obj_main_EffChangeBall, PRI_COMM_CHANGE );
		CATS_ObjectEnableCap( ptr->cap[ CAPCOMM_ID_M_BALL ], CATS_ENABLE_FALSE );

	}
}

//-----------------------------------------------------------------------------
/**
 *	@brief	通信ポケモン用状態異常アイコンをセット
 *
 *	@param	COMM_POKE_PTR ptr
 *	@param	AnimeSeq
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static void CommPokeEffect_SetActor( COMM_POKE_PTR ptr, u16 AnimeSeq )
{
	const MONS_INFO* info;
	s16 px = SUB_KAWARA_POS_X + START_POKE_ENEMY_POS_X_OFS * ptr->LineID;
	s16 py = SUB_ICON_EFFECT_POS_Y;
	CATS_ACT_PTR actor = ptr->cap[ CAPCOMM_ID_M_EFF ];

	info = PCLACT_GetMonsInfo( PokeAct_GetPclActPtr( ptr->act[ ptr->PokeIdx ] ) );

	// サイズが大きいポケモンはエフェクトの位置を高くする
	if( info->CellType ) // big size
	{
		py -= COMM_BIGPOKE_EFF_DEC;
	}

	CATS_ObjectPosSetCap( actor, px, py );
	CATS_ObjectAnimeSeqCheckSetCap( actor, AnimeSeq );
	CATS_ObjectEnableCap( actor, CATS_ENABLE_TRUE );
}

//-----------------------------------------------------------------------------
/**
 *	@brief	通信ポケモンエフェクト
 *
 *	@param	COMM_POKE_PTR ptr
 *	@param	BREAK_COMM_POKE_PARAM* cpp
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static void CommPokeEffect( COMM_POKE_PTR ptr, const BREAK_COMM_POKE_PARAM* cpp )
{
	// ハイテンション
	if( cpp->bHighTension )
	{
		u32 AnimeSeq = NANR_break_obj_main_Aura_L;

		CATS_ObjectAnimeSeqCheckSetCap( ptr->cap[ CAPCOMM_ID_M_AURA ], AnimeSeq );
		CATS_ObjectEnableCap( ptr->cap[ CAPCOMM_ID_M_AURA ], CATS_ENABLE_TRUE );
	}
	// 非ハイテンション
	else
	{
		// オーラ
		if( cpp->Tension >= TENSION_AURA )
		{
			DrawTensionAuraS( ptr->cap[ CAPCOMM_ID_M_AURA ], cpp->Tension, FALSE );
		}
		else
		{
			CATS_ObjectEnableCap( ptr->cap[ CAPCOMM_ID_M_AURA ], CATS_ENABLE_FALSE );
		}
	}

//		HOSAKA_PRINT("[%d,%d] STAMINA:%d MAX:%d \n", ptr->NetID, ptr->PokeIdx, cpp->Stamina, ptr->StaminaMax[ptr->PokeIdx] );

	// 気絶
	if( cpp->Stamina <= 0 )
	{
		u32 AnimeSeq = NANR_break_obj_main_EffConfusion;

		CommPokeEffect_SetActor( ptr, AnimeSeq );

		CATS_ObjectEnableCap( ptr->cap[ CAPCOMM_ID_M_AURA ], CATS_ENABLE_FALSE );

		// POKEACT::STOP
		PokeAct_SetAnm( ptr->act[ ptr->PokeIdx ], ANM_TYPE_STOP );
	}
	else
	// 汗
	{
		fx32 Stamina = cpp->Stamina * FX32_ONE;
		fx32 StaminaMax = ptr->StaminaMax[ ptr->PokeIdx ] * FX32_ONE;

		if( SweatCalcSpeed( ptr->cap[ CAPCOMM_ID_M_EFF ], Stamina, StaminaMax ) )
		{
			u32 AnimeSeq = NANR_break_obj_main_EffSweat;

			CommPokeEffect_SetActor( ptr, AnimeSeq );

			// POKEACT::WALK
			PokeAct_SetAnm( ptr->act[ ptr->PokeIdx ], ANM_TYPE_WALK );
		}
		// ハイテンション
		else if( cpp->bHighTension )
		{
			// POKEACT::DASH
			PokeAct_SetAnm( ptr->act[ ptr->PokeIdx ], ANM_TYPE_DASH );
		}
		// なし
		else
		{
			CATS_ObjectEnableCap( ptr->cap[ CAPCOMM_ID_M_EFF ], CATS_ENABLE_FALSE );
			// POKEACT::RUN
			PokeAct_SetAnm( ptr->act[ ptr->PokeIdx ], ANM_TYPE_RUN );
		}
	}
}

//-----------------------------------------------------------------------------
/**
 *	@brief
 *
 *	@param	COMM_POKE_PTR ptr
 *	@param	BREAK_COMM_POKE_PARAM* cpp
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static void CommKawara( COMM_POKE_PTR ptr, const BREAK_COMM_POKE_PARAM* cpp )
{
	if( ptr->BreakCountPre != cpp->BreakCount )
	{
		s16 px, py;
		u32 BreakNum = cpp->BreakCount % 10;
		u32 AnimeSeq = NANR_break_obj_main_S_Block5 - BreakNum / 2;

		// かわら状態遷移
		if( BreakNum )
		{
			CATS_ObjectAnimeSeqCheckSetCap( ptr->cap[ CAPCOMM_ID_M_KAWARA ], AnimeSeq );
		}
		else
		{
			// 補填
			AnimeSeq = NANR_break_obj_main_S_BlockCharge;
			CATS_ObjectAnimeSeqCheckSetCap( ptr->cap[ CAPCOMM_ID_M_KAWARA ], AnimeSeq );
		}

		// 破壊エフェクト
		px = SUB_KAWARA_POS_X + START_POKE_ENEMY_POS_X_OFS * ptr->LineID;
		py = SUB_KAWARA_POS_Y + 3 * (BreakNum/2) - 8;
		CATS_ObjectPosSetCap( ptr->cap[ CAPCOMM_ID_M_KAWARA_EFF ], px, py );

		AnimeSeq = NANR_break_obj_main_EffBreak_S;
		CATS_ObjectAnimeSeqSetCap( ptr->cap[ CAPCOMM_ID_M_KAWARA_EFF ], AnimeSeq );
		CATS_ObjectEnableCap( ptr->cap[ CAPCOMM_ID_M_KAWARA_EFF ], CATS_ENABLE_TRUE );

		// 前回の値を保持
		ptr->BreakCountPre = cpp->BreakCount;

//		HOSAKA_PRINT( "[%d]BreaCount = %d \n", ptr->NetID, cpp->BreakCount );
	}
}

//-----------------------------------------------------------------------------
/**
 *	@brief	通信ポケモン用 交代タスク
 *
 *	@param	TCB_PTR tcb
 *	@param	work
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static void TCB_CommChangeTask( TCB_PTR tcb, void* work )
{
	COMM_POKE_PTR ptr = work;

	switch( ptr->ChangeSeq )
	{
		case 0:
			// 煙再生
			{
				CATS_ACT_PTR cap = ptr->cap[CAPCOMM_ID_M_SMOKE ];
				CATS_ObjectAnimeReStartCap( cap );
				CATS_ObjectEnableCap( cap, CATS_ENABLE_TRUE );

				ptr->ChangeSeq++;
			}
			break;
		case 1:
			if( ++ptr->ChangeTimer >= CHANGE_POKEGRA_SYNC )
			{
				CATS_ACT_PTR cap = ptr->cap[CAPCOMM_ID_M_BALL ];
				u16 AnimeSeq = NANR_break_obj_main_EffChangeBall;

				// 現在のポケモンを消す
				PokeAct_DispCnt( ptr->act[ ptr->PokeIdx ], 0 );

				// モンスターボール表示
				CATS_ObjectAnimeSeqSetCap( cap, AnimeSeq );
				CATS_ObjectAutoAnimeSetCap( cap, FALSE );
				CATS_ObjectEnableCap( cap, CATS_ENABLE_TRUE );

				ptr->ChangeTimer = 0;
				ptr->ChangeSeq++;
			}
			break;
		case 2:
			// ボール移動(回収)
			{
				s16 px, py;
				s16 my;

				CATS_ObjectPosGetCap( ptr->cap[ CAPCOMM_ID_M_BALL ], &px, &py );
				my = ( BALL_OUT_TARGET_POS - py ) / BALL_OUT_SPEED_DIV;

				if( py <= BALL_OUT_TARGET_POS || my == 0 )
				{
					ptr->ChangeSeq++;
					// ウェイトが0以下だったらSEQを飛ばす
					if( CHANGE_WAIT_SYNC <= 0 )
					{
						ptr->ChangeSeq++;
					}
				}
				else
				{
					CATS_ObjectPosSetCap_SubSurface( ptr->cap[ CAPCOMM_ID_M_BALL ], px, py + my ,OBJ_DISTANCE );
				}
			}
			break;
		case 3:
			// ウェイト
			if( ++ptr->ChangeTimer >= CHANGE_WAIT_SYNC )
			{
				ptr->ChangeTimer = 0;
				ptr->ChangeSeq++;
			}
			break;
		case 4:
			// ボール移動（落下）
			{
				s16 px, py;
				s16 val;

				CATS_ObjectPosGetCap( ptr->cap[ CAPCOMM_ID_M_BALL ], &px, &py );

				val = MATH_ABS( BALL_IN_DEF_POS - BALL_IN_DEF_SPD - py );
				if( val ){ val /= BALL_IN_SPEED_DIV; }	///< ZeroDiv 対策
				py += val + BALL_IN_DEC_POS;

				if( py >= START_POKE_ENEMY_POS_Y )
				{
					// 落下終了処理
					px = START_POKE_ENEMY_POS_X + START_POKE_ENEMY_POS_X_OFS * ptr->LineID;
					py = START_POKE_ENEMY_POS_Y;

					// ボールアニメ開始
					CATS_ObjectPosSetCap( ptr->cap[ CAPCOMM_ID_M_BALL ], px, py );
					CATS_ObjectAutoAnimeSetCap( ptr->cap[ CAPCOMM_ID_M_BALL ], TRUE );

					// 煙表示
					CATS_ObjectAnimeReStartCap( ptr->cap[ CAPCOMM_ID_M_SMOKE ] );

					ptr->ChangeSeq++;
				}
				else
				{
					CATS_ObjectPosSetCap_SubSurface( ptr->cap[ CAPCOMM_ID_M_BALL ], px, py ,OBJ_DISTANCE );
				}
			}
			break;
		case 5:
			// 煙ウェイト
			if( ++ptr->ChangeTimer >= CHANGE_POKEGRA_SYNC )
			{
				// ボール消す
				CATS_ObjectEnableCap( ptr->cap[ CAPCOMM_ID_M_BALL ], CATS_ENABLE_FALSE );

				// 交代、グラ変更
				PokeAct_DispCnt( ptr->act[ ptr->ChangeAfterIdx ], 1 );
				PokeAct_ShdwDispCnt( ptr->act[ ptr->ChangeAfterIdx ], 0 ); // 影表示
				// ID変更
				ptr->PokeIdx = ptr->ChangeAfterIdx;

				ptr->ChangeTimer = 0;
				ptr->ChangeSeq++;
			}
			break;
		case 6:
			{
				HOSAKA_PRINT("[%d]交換TCB終了\n",ptr->NetID);
				ptr->tcbChange = NULL;
				ptr->bChange = 0;
				TCB_Delete( tcb );
			}
			break;
		default : GF_ASSERT(0);
	}
}

//-----------------------------------------------------------------------------
/**
 *	@brief	通信ポケモン 交代開始
 *
 *	@param	COMM_POKE_PTR ptr
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static void CommPoke_StartChangeTask( COMM_POKE_PTR ptr )
{
	HOSAKA_PRINT("[%d]TCB開始\n",ptr->NetID);
	ptr->ChangeSeq = 0;
	ptr->ChangeTimer = 0;
	ptr->bChange = 1;
	ptr->tcbChange = TCB_Add( TCB_CommChangeTask, ptr, 1 );
}

//-----------------------------------------------------------------------------
/**
 *	@brief	通信ポケモン ReciveShareDataから情報を取得、反映
 *
 *	@param	COMM_POKE_PTR ptr
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static void CommPoke_Proc( COMM_POKE_PTR ptr )
{
	COMM_EVENT_COMMON_DATA* data = PTFrame_GetEvtComCmnData(ptr->PkthlnWork);
	BREAK_PARENT_DATA* parent = PKTHLN_CommPack_GetData(&data->ReciveShareData);
	const BREAK_COMM_POKE_PARAM* cpp = &parent->cpp[ptr->NetID];

	// 交代判定
	if( ptr->PokeIdx == cpp->PokeIdx )
	{
		// オーラ、状態異常アイコン処理
		CommPokeEffect( ptr, cpp );
	}
	else
	{
		// 交換中はエフェクトを消す
		CATS_ObjectEnableCap( ptr->cap[ CAPCOMM_ID_M_EFF ], CATS_ENABLE_FALSE );
		CATS_ObjectEnableCap( ptr->cap[ CAPCOMM_ID_M_AURA ], CATS_ENABLE_FALSE );
	}

	// カワラ処理
	CommKawara( ptr, cpp );

	// 交代演出
	if( ptr->bChange == 0 && ptr->PokeIdx != cpp->PokeIdx )
	{
		GF_ASSERT( cpp->PokeIdx < ENTRY_MAX );

		ptr->ChangeAfterIdx = cpp->PokeIdx;
		// 交代演出開始
		CommPoke_StartChangeTask( ptr );
	}
}

//-----------------------------------------------------------------------------
/**
 *	@brief	ポケグラ用CAPを設定/追加
 *
 *	@param	BREAK_POKE_CNT_PTR cnt
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static void OBJ_AddPokegra( CATS_ACT_PTR* ppCap, CATS_SYS_PTR csp, CATS_RES_PTR crp )
{
	TCATS_OBJECT_ADD_PARAM_S prm = {0};
	int i;

	GF_ASSERT(csp);
	GF_ASSERT(crp);

	for( i=0; i<OBJ_POKEGRA_M_MAX; i++ )
	{
		prm.id[0] = CHR_ID_M_POKEGRA + i;
		prm.id[1] = PAL_ID_M_POKEGRA + i;
		prm.id[2] = CEL_ID_POKEGRA;
		prm.id[3] = ANM_ID_POKEGRA;
		prm.d_area = NNS_G2D_VRAM_TYPE_2DMAIN;
		prm.x = START_POKE_MINE_POS_X;
		prm.y = START_POKE_MINE_POS_Y;
		prm.pri = PRI_POKE_MINE;
		prm.bg_pri = 2;

		ppCap[ CAP_ID_M_POKEGRA + i ] = CATS_ObjectAdd_S_SubDistance( csp, crp, &prm, OBJ_DISTANCE );
		CATS_ObjectAutoAnimeSetCap( ppCap[ CAP_ID_M_POKEGRA + i ], TRUE );
	}

	for( i=0; i<OBJ_POKEGRA_S_MAX; i++ )
	{
		prm.id[0] = CHR_ID_S_POKEGRA + i;
		prm.id[1] = PAL_ID_S_POKEGRA + i;
		prm.id[2] = CEL_ID_POKEGRA;
		prm.id[3] = ANM_ID_POKEGRA;
		prm.d_area = NNS_G2D_VRAM_TYPE_2DSUB;
		prm.x = BENCH_POKE_POS_X;
		prm.y = BENCH_POKE_POS_Y + BENCH_POKE_POS_Y_OFS * i;
		prm.pri = PRISUB_POKE_0 + i;

		ppCap[ CAP_ID_S_POKEGRA_A + i ] = CATS_ObjectAdd_S_SubDistance( csp, crp, &prm, OBJ_DISTANCE );
		CATS_ObjectAutoAnimeSetCap( ppCap[ CAP_ID_S_POKEGRA_A + i ], TRUE );
	}
}

//-----------------------------------------------------------------------------
/**
 *	@brief	ポケグラを転送
 *
 *	@param	BREAK_POKE_PTR ptr
 *	@param	CapIdx
 *	@param	TeamIdx
 *	@param	PokeIdx
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static void OBJ_TransPokeGra( BREAK_POKE_PTR ptr, u16 CapIdx, u8 TeamIdx, u8 PokeIdx, BOOL b_LCD_main )
{
	MONS_INFO info;
	HEAPID heapID = ptr->HeapID;
	PKTHLN_PTR work = ptr->work;
	CATS_ACT_PTR cap = ptr->cap[ CapIdx ];

	PTFrame_SetMonsInfo( work, TeamIdx, PokeIdx, &info );
	CATS_PokeGraTrans( cap, &info, b_LCD_main, FALSE, heapID );
}

//-----------------------------------------------------------------------------
/**
 *	@brief
 *
 *	@param	BREAK_POKE_PTR ptr
 *	@param	state
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static void SetState( BREAK_POKE_PTR ptr, BPOKE_STATE state )
{
	// -- State終了処理 --
	switch( ptr->State )
	{
	case BPOKE_STATE_PANIC :
		break;
	}

	// -- State初期化処理 --
	switch ( state )
	{
	case BPOKE_STATE_PANIC :
		// AP:失敗
		PTFrame_AddActionPoint( ptr->work, PTFrameGetCurrentID(ptr->work), ptr->PokeIdx, ADD_TYPE_FAIL, 1 );
		ptr->Param[ ptr->PokeIdx ].Stamina = 0;
		ptr->HealTimer = 0;
		HOSAKA_PRINT("Panic ... \n" );
		break;

	case BPOKE_STATE_CHANGE :
		// AP:交代
		PTFrame_AddActionPoint( ptr->work, PTFrameGetCurrentID(ptr->work), ptr->PokeIdx, ADD_TYPE_CHANGE, 1 );
		ptr->ChangeTimer = 0;
		// テンション下げる
		{
			int val = ptr->Tension - TENSION_DEC_CHANGE;
			ptr->Tension = MATH_CLAMP( val, 0, TENSION_MAX );
		}
		// ハイテンションだった場合、終了
		if( ptr->bHighTension ){ HighTension_End( ptr ); }
		// ポケモンIDX変更
		ptr->PokeIdx++;
		if( ptr->PokeIdx >= ENTRY_MAX )
		{
			ptr->PokeIdx = 0;
		}
		break;
	}

	// 共通処理
	ptr->State = state;
	ptr->SubSeq = 0;
	ptr->AttackTimer = 0;
}

//-----------------------------------------------------------------------------
/**
 *	@brief	テンション下がる
 *
 *	@param	BREAK_POKE_PTR ptr
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static void TensionProc( BREAK_POKE_PTR ptr )
{
	if( ptr->State == BPOKE_STATE_CHANGE ){ return; }

	// -- ハイテンション処理 --
	if( ptr->bHighTension )
	{
		if( ++ptr->TensionTimer >= TENSION_SYNC )
		{
			HighTension_End( ptr );
		}
	}
	// -- 通常処理 --
	else
	{
		if( ptr->Tension > 0 )
		{
			if( ++ptr->TensionTimer >= TENSION_DEC_SYNC )
			{
				ptr->TensionTimer = 0;
				ptr->Tension--;
			}

			// オーラ小チェック
			if( ptr->Tension >= TENSION_AURA )
			{
				DrawTensionAuraS( ptr->cap[ CAP_ID_M_AURA ], ptr->Tension, TRUE );
			}
		}
		else
		{
			// オーラ消ゆ……
			CATS_ObjectEnableCap( ptr->cap[ CAP_ID_M_AURA ], CATS_ENABLE_FALSE );
		}
	}
}

//-----------------------------------------------------------------------------
/**
 *	@brief	テンションUP
 *
 *	@param	BREAK_POKE_PTR ptr
 *	@param	bCritical
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static void TensionAdd( BREAK_POKE_PTR ptr, BOOL bCritical, u16 breakNum )
{
	GF_ASSERT( ptr->bHighTension == FALSE );

	if( bCritical ){ ptr->Tension += TENSION_ADD_CRITICAL; }
	if( breakNum ){ ptr->Tension += TENSION_ADD_BREAK * breakNum; }
	if( ptr->Tension > TENSION_MAX ){ ptr->Tension = TENSION_MAX; }

	if( ptr->Tension >= TENSION_MAX )
	{
		// ハイテンション移行
		HighTension_Start( ptr );
	}
	HOSAKA_PRINT("tenison : %d \n", ptr->Tension );
}

//-----------------------------------------------------------------------------
/**
 *	@brief	スタミナ判定・表現
 *
 *	@param	CATS_ACT_PTR cap
 *	@param	aseq
 *	@param	stamina
 *	@param	staminaMax
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static BOOL SweatCalcSpeed( CATS_ACT_PTR cap, fx32 stamina, fx32 staminaMax )
{
	fx32 StaminaPar;

	StaminaPar = FX_Div( stamina, staminaMax );
	StaminaPar = ( StaminaPar *  100 ) >> FX32_SHIFT;

	if( StaminaPar <= PANIC_SWEAT_POINT )
	{
		fx32 speed = (100 - StaminaPar) * 2;

#if 0
		HOSAKA_PRINT( "StaminaPar:%d SpeedPar:%d, %f \n",
				StaminaPar, speed, FX_FX32_TO_F32(FX32_CONST(speed)/100) );
#endif

		// 速度変更
		CATS_ObjectAutoAnimeSpeedSetCap( cap, FX32_CONST(speed)/100 );

		return TRUE;
	}

	return FALSE;
}



//-----------------------------------------------------------------------------
/**
 *	@brief	ハイテンション開始
 *
 *	@param	BREAK_POKE_PTR ptr
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static void HighTension_Start( BREAK_POKE_PTR ptr )
{
	ptr->bHighTension = TRUE;
	ptr->TensionTimer = 0;
	CATS_ObjectAnimeSeqSetCap( ptr->cap[ CAP_ID_M_AURA ], NANR_break_obj_main_Aura_L ); // オーラ大
	CATS_ObjectAutoAnimeSpeedSetCap( ptr->cap[ CAP_ID_M_AURA ], FX32_ONE );
	Snd_SePlay( SE_BREAK_RED );
	HOSAKA_PRINT("high tension !!!\n" );
}

//-----------------------------------------------------------------------------
/**
 *	@brief	ハイテンション終了
 *
 *	@param	BREAK_POKE_PTR ptr
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static void HighTension_End( BREAK_POKE_PTR ptr )
{
	ptr->bHighTension = FALSE;
	ptr->TensionTimer = 0;
	ptr->Tension = 0;
	ptr->Param[ ptr->PokeIdx ].Stamina = TENSION_STAMINA_RESET;
	CATS_ObjectEnableCap( ptr->cap[ CAP_ID_M_AURA ], CATS_ENABLE_FALSE );
}

//-----------------------------------------------------------------------------
/**
 *	@brief	ポケアクター初期化
 *
 *	@param	POKE_ACT_CNT_PTR PokeActCntPtr
 *	@param	u8 netID
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static void PKACT_Init( POKE_ACT_CNT_PTR PokeActCntPtr, const u8 CurrentID )
{
	int i;
	int j;
	int NetID;
	int sx;
	int sy;
	int EnemyCnt = 0;
	POKE_ACT_PTR poke_ptr;

	for( i=0; i<ENTRY_MEMBER_NUM_MAX; i++ )
	{
		// 自分のポケモンはPOKEGRAで表示するので、ここでは表示回避
		if( i == CurrentID )
		{
			continue;
		}

		// 敵のポケモンを表示
		for( j=0; j<ENTRY_MAX; j++ )
		{
			poke_ptr = PokeAct_GetPokeActPtr( PokeActCntPtr, EnemyCnt * ENTRY_MAX + j );

			sx = START_POKE_ENEMY_POS_X + START_POKE_ENEMY_POS_X_OFS * EnemyCnt;
			sy = START_POKE_ENEMY_POS_Y;

			PokeAct_SetPriority(poke_ptr, PRI_COMM_POKE);
			PokeAct_SetPosShadow( poke_ptr, sx, sy );
			PokeAct_SetDir(poke_ptr, POKE_DIR_DOWN);

			// 手前だけ表示
			PokeAct_DispCnt(poke_ptr, (j==0) );
			PokeAct_ShdwDispCnt( poke_ptr, 0 );	// 影を消す
		}

		EnemyCnt++;
	}
}

//-----------------------------------------------------------------------------
/**
 *	@brief
 *
 *	@param	CATS_ACT_PTR cap
 *	@param	Tension
 *	@param	bSE	TRUE:オーラ発動時にSEを鳴らす
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static void DrawTensionAuraS( CATS_ACT_PTR cap, u16 Tension, BOOL bSE )
{
	fx32 val;
	fx32 speed = 0;

	// オーラ速度変更
	val = Tension - TENSION_AURA;

	if( val )
	{
		speed = ( val << FX32_SHIFT ) / 10;
	}

	// 最低速度設定
	if( speed < TENSION_AURA_MIN_SPEED ){ speed = TENSION_AURA_MIN_SPEED; }

	CATS_ObjectAutoAnimeSpeedSetCap( cap, speed );
	CATS_ObjectAnimeSeqCheckSetCap( cap, NANR_break_obj_main_Aura_S );

	// オーラ発動時
	if( bSE )
	{
		if( CATS_ObjectEnableGetCap( cap ) == CATS_ENABLE_FALSE )
		{
			Snd_SePlay( SE_BREAK_BLUE );
		}
	}

	CATS_ObjectEnableCap( cap, CATS_ENABLE_TRUE );
}

//-----------------------------------------------------------------------------
/**
 *	@brief	ベンチポケモンと状態アイコンの位置をセットする
 *
 *	@param	u32 PokeIdx
 *	@param	px
 *	@param	py
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static void SetBenchPokePos( BREAK_POKE_PTR ptr, u32 PokeIdx, s16 px, s16 py )
{
	HOSAKA_PRINT("set pokegra pos{%d,%d}\n",px,py);
	// ポケグラ移動
	CATS_ObjectPosSetCap_SubSurface( ptr->cap[ PokeIdx ], px, py, OBJ_DISTANCE );
	// エフェクト移動
	py += BENCH_POKEEFF_POS_Y_DIFF;
	CATS_ObjectPosSetCap_SubSurface( ptr->cap[ PokeIdx + 2 ], px, py, OBJ_DISTANCE );
}

